#include "stdafx.h"
#include "EphemParam.h"
#include <boost/foreach.hpp>
#include "EphemParamDlg.h"

auto_ptr<CEphemParam>	CEphemParam::s_pStaticParam;
CCriticalSection		CEphemParam::s_cs;
int						CEphemParam::s_count = 0;

CEphemParam::CEphemParam(LPCTSTR stzFileSettingsName)
{
	using namespace boost::property_tree;
	tptree pt;

	try
	{
		tifstream in(stzFileSettingsName);
		xml_parser::read_xml(in, pt);

		m_strCurrentEphem = pt.get(_T("Param.EphemsParam.current"), _T(""));

		try
		{
			const tptree& Ephems = pt.get_child(_T("Param.EphemsParam.Ephems"));

			BOOST_FOREACH(const boost::property_tree::tptree::value_type& ephem, Ephems)
			{
				const tptree& values = ephem.second;
				std::tstring strName = values.get<std::tstring>(_T("name"));
				std::tstring strPath = values.get<std::tstring>(_T("path"));
				m_mapEphemPath[strName] = strPath;
			}

		}
		catch(xml_parser_error &e)
		{
			throw CCustomException(_T("line %d file %s:\n%s"), e.line(), e.filename().c_str(), e.message().c_str());
		}
		catch (const ptree_bad_data& error)
		{
			throw CCustomException(_T("ptree_bad_data: %s"), error.what());
		}
		catch (const ptree_bad_path& error)
		{
			throw CCustomException(_T("ptree_bad_path: %s"), error.what());
		}
		catch(...)
		{
			
		}
	}
	catch(xml_parser_error &e)
	{
		throw CCustomException(_T("line %d file %s:\n%s"), e.line(), e.filename().c_str(), e.message().c_str());
	}
	catch (const ptree_bad_data& error)
	{
		throw CCustomException(_T("ptree_bad_data: %s"), error.what());
	}
	catch (const ptree_bad_path& error)
	{
		throw CCustomException(_T("ptree_bad_path: %s"), error.what());
	}
	catch (const CCustomException& e)
	{
		throw e;
	}
	catch(...)
	{
		throw CCustomException(_T("Unknown error"));
	}
	++s_count;
}

CEphemParam::CEphemParam(void)
{
	CAutoCriticalSection acs(s_cs);
	if(s_pStaticParam.get() == NULL)
	{
		LPCTSTR stzConfigFile = GetFileName();
		if(stzConfigFile == NULL || stzConfigFile[0] == 0)
			throw CCustomException(_T("CRadaParam::CRadaParam: empty config file name"));

		s_pStaticParam = auto_ptr<CEphemParam>(new CEphemParam(stzConfigFile));
	}
	*this = *s_pStaticParam;
	++s_count;
}

CEphemParam::~CEphemParam(void)
{
	--s_count;
	if(s_count == 1) // only static still destroy it
	{
		s_pStaticParam.reset();
	}

	if(s_pStaticParam.get() == this) // this is last? should store settings
	{
		CStdString strError;
		using namespace boost::property_tree;
		tptree pt;
		LPCTSTR strfile = GetFileName();
		try
		{
			tifstream in(strfile);
			xml_parser::read_xml(in, pt);
			tptree& EphemsParamOld = pt.get_child(_T("Param.EphemsParam"));
			EphemsParamOld.clear();

			pt.put(_T("Param.EphemsParam.current"), m_strCurrentEphem.c_str());
			pt.put(_T("Param.EphemsParam.Ephems"), _T(""));
			tptree& EphemsParamNew = pt.get_child(_T("Param.EphemsParam.Ephems"));

			MapEphemPath::const_iterator it = m_mapEphemPath.begin();
			MapEphemPath::const_iterator end = m_mapEphemPath.end();
			for( ;it!=end; ++it)
			{
				tptree::iterator itEphem = EphemsParamNew.push_back( make_pair(_T("Ephem"), _T("")) );
				tptree& Ephem = itEphem->second; 
				Ephem.put(_T("name"), it->first);
				Ephem.put(_T("path"), it->second);
			}
			tofstream out(GetFileName());
			xml_parser::write_xml(out, pt);
		}
		catch(xml_parser_error &e)
		{
			throw CCustomException(_T("line %d file %s:\n%s"), e.line(), e.filename().c_str(), e.message().c_str());
		}
		catch(...)
		{
			strError = _T("Unknown error");
		}

		if(strError.length())
		{
			strError.Format(_T("Error storing rada param: %s"), strError.c_str());
			AfxMessageBox(strError);
		}
	}
}


LPCTSTR CEphemParam::GetCurrentEphem() const
{
	return m_strCurrentEphem;
}

LPCTSTR CEphemParam::GetCurrentEphemPath() const
{
	if(m_strCurrentEphem.IsEmpty())
		throw CCustomException(_T("work Ephem not select"));
	MapEphemPath::const_iterator it = m_mapEphemPath.find(m_strCurrentEphem);
	if(it == m_mapEphemPath.end())
		throw CCustomException(_T("can not found path for selected Ephem"));
	return it->second;
}

bool CEphemParam::SetCurrentEphem(LPCTSTR stzCurEphem)
{
	m_strCurrentEphem = stzCurEphem;
	return true;
}

LPCTSTR CEphemParam::GetEphemName(LPCTSTR stzEphemName) const
{
	MapEphemPath::const_iterator it = m_mapEphemPath.find(stzEphemName);
	if(it == m_mapEphemPath.end())
		return NULL;
	else
		return it->first;
}

LPCTSTR CEphemParam::GetEphemPath(LPCTSTR stzEphemName) const
{
	MapEphemPath::const_iterator it = m_mapEphemPath.find(stzEphemName);
	if(it == m_mapEphemPath.end())
		return NULL;
	else
		return it->second;
}

int CEphemParam::GetCount() const
{
	return m_mapEphemPath.size();
}

bool CEphemParam::GetNames(list<LPCTSTR> &listNames) const
{
	MapEphemPath::const_iterator it = m_mapEphemPath.begin();
	MapEphemPath::const_iterator end = m_mapEphemPath.end();
	for(; it != end; ++it)
	{
		listNames.push_back(it->first);
	}
	return true;
}

bool CEphemParam::AddEphem(LPCTSTR stzEphemName, LPCTSTR stzEphemPath)
{
	m_mapEphemPath[stzEphemName] = stzEphemPath;
	return true;
}

bool CEphemParam::RemoveEphem(LPCTSTR stzEphemName)
{
	m_mapEphemPath.erase(stzEphemName);
	return true;
}

bool CEphemParam::ShowSettings()
{
	CEphemParam tmp;
	CEphemParamDlg dlg(&tmp);
	
	if(dlg.DoModal() == IDOK)
	{
		*s_pStaticParam = tmp;
	}
	
	return true;
}